/*******************************************************************************
 * Copyright (c) 2008-2009 zhang yuexiang.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package org.xfeep.asura.bootstrap;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

import org.xfeep.asura.core.event.ServiceEventCenter;
import org.xfeep.asura.core.reflect.FieldItem;

public class ResetableExcutorServiceUtil {
	
	public static ServiceEventCenter serviceEventCenter;
	
	public static class CountableBlockingQueue<E> extends LinkedBlockingQueue<E> {
		private static final long serialVersionUID = 1L;

		AtomicInteger insertedCount = new AtomicInteger(0);
		
		public AtomicInteger getInsertedCount() {
			return insertedCount;
		}

		public CountableBlockingQueue() {
		}

		@Override
		public boolean offer(E e, long timeout, TimeUnit unit)
				throws InterruptedException {
			insertedCount.incrementAndGet();
			return super.offer(e, timeout, unit);
		}

		@Override
		public boolean offer(E e) {
			insertedCount.incrementAndGet();
			return super.offer(e);
		}

		@Override
		public E peek() {
			return super.peek();
		}
		
		@Override
		public E take() throws InterruptedException {
			E e =  super.take();
//			if (e != null){
//				insertedCount.decrementAndGet();
//			}
			return e;
		}

		@Override
		public E poll() {
			E e =  super.poll();
//			if (e != null){
//				insertedCount.decrementAndGet();
//			}
			return e;
		}

		@Override
		public E poll(long timeout, TimeUnit unit) throws InterruptedException {
			E e =  super.poll(timeout, unit);
//			if (e != null){
//				insertedCount.decrementAndGet();
//			}
			return e;
		}

		@Override
		public void put(E e) throws InterruptedException {
			super.put(e);
			insertedCount.incrementAndGet();
		}

		@Override
		public boolean remove(Object o) {
			boolean rt = super.remove(o);
//			if (rt){
//				insertedCount.decrementAndGet();
//			}
			return rt;
		}
	}
	
	public static ExecutorService getExecutorService(int coreThreads){
		ThreadPoolExecutor threadPoolExecutor = 
			new ThreadPoolExecutor(coreThreads,coreThreads,Long.MAX_VALUE, TimeUnit.MICROSECONDS, new LinkedBlockingQueue<Runnable>());
		return threadPoolExecutor;
	}
	
	public static CountDownLatch countDownLatch = new CountDownLatch(1);
	
	public static void waitAllfinish(long slice){
//		if ( ! (executorService instanceof ThreadPoolExecutor ) ){
//			throw new IllegalArgumentException("executorService must be instance of  ThreadPoolExecutor");
//		}
//		try {
//			FieldItem mainLockField = new FieldItem(executorService.getClass(), "mainLock");
//			ReentrantLock mainLock = (ReentrantLock) mainLockField.getValue(executorService);
//			while(true){
//				Thread.sleep(slice);
//				mainLock.lock();
//				try{
//					ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor)executorService;
//					CountableBlockingQueue<Runnable> queue = (CountableBlockingQueue<Runnable>)poolExecutor.getQueue();
//					if( queue.getInsertedCount().intValue() > poolExecutor.getCompletedTaskCount() || poolExecutor.getActiveCount() > 0){
//						continue;
//					}else{
//						break;
//					}
//				}finally{
//					mainLock.unlock();
//				}
//				
//			}
//		} catch (Throwable e1) {
//			e1.printStackTrace();
//		} 
//		if (serviceEventCenter == null){
//			return;
//		}
		while(true) {
			if (serviceEventCenter.getWaintingEventCount() == 0){
				return;
			}
			try {
				Thread.sleep(slice);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
//			try {
//				countDownLatch.await(slice, TimeUnit.NANOSECONDS);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
			
		}
		
	}
}
